本系列文已重新編排並新增內容出版成冊,若您喜歡透過書籍來閱讀的話,歡迎至天瓏書局下單選購唷!
經過測試金字塔模型的協助後,我們大致上瞭解要怎麼替專案加入對應的測試類型;並且在上一章節中我們也提到了針對「單元測試」類型做測試工具挑選時,可以從需求表中拉出各種工具做比較。
而接下來我們要談談在選擇這些工具後,我們要如何來思考針對「單元測試」的部分,測試情境與測試案例要怎麼撰寫以及需要注意的地方。
提供測試環境的工具一般會給予測試情境與測試案例的相關 API,而測試情境與案例最主要的用意是用來幫助我們規劃與整理整個測試邏輯,並且在我們測試案例錯誤的時候同時提供相對應的資訊。
接下來我們以「貓咪作為元件」為故事主軸來談談單元測試的思路會是怎麼撰寫。
首先我們假設「貓咪」元件會提供下列功能:
而以使用者角度上來看,我們會對「貓咪」做出這些事情:
接著我們就可以以元件作為情境來定義出各種使用上的測試案例:
describe('貓咪', () => {
it('摸摸,應該會發出「呼嚕嚕」聲', () => {
// ...
})
it('餵食,應該會發出「呼嚕嚕」聲', () => {
// ...
})
it('拿玩具逗,應該會發出「呼嚕嚕」聲', () => {
// ...
})
it('什麼都不做,應該推倒眼前看到的所有東西', () => {
// ...
})
})
但真實的測試案例不會這麼簡單,總會有一些例外狀況,那麼測試案例應該要包含哪些要素比較好?
在設定測試案例時,總會有百百種情況,但是我們不可能每個都寫出來,而根據測試案例的類型主要可以分為三種路徑
同樣以貓被摸摸作為例子來看,假設對於貓來說能夠接受摸摸的情況只限於「頭與下巴」,而喜歡被摸的部分只有「下巴」,那麼測試案例路徑就可以這麼定義:
describe('貓咪', () => {
// Happy Path
it('摸摸下巴,應該會發出「呼嚕嚕」聲', () => {
// ...
})
// Sad Path
it('摸摸頭,應該沒反應', () => {
// ...
})
// Bad Path
it('摸摸肚子,應該拋出錯誤', () => {
// ...
})
})
而以各個路徑優先度來說,我們應當盡可能的先完善 Happy Path 與 Sad Path 的各種案例,因為對於實際專案上來說,這些內容是我們預期元件或函式本身應提供的內容。
然而 Bad Path 通常是建立已知哪些情況會是「不正確的使用」,我們只能就已知的狀況來預防。然而,這一部分其實再怎麼縝密,都還是會有極其例外的事情發生:
describe('貓咪', () => {
// ...
// Bad Path
it('摸摸肚子,應該拋出錯誤', () => {
// ...
})
it('摸摸尾巴,應該拋出錯誤', () => {
// ...
})
it('摸摸手,應該拋出錯誤', () => {
// ...
})
it('摸摸腳,應該拋出錯誤', () => {
// ...
})
// 舉不完
})
因此透過測試來作防禦所有不合理的行為是不治本的行為,我應該從受測物本身提供的操作或是產品規劃上來去考量相對治本的方式;比方在「貓咪」元件上透過程式設計的部分,規劃「摸摸」行為只開放「頭」與「下巴」的部位,從開發階段就阻止其他開發者誤用「摸摸」方法,到最後真的有其必要特別拋出時才針對這一部分寫 Bad Path 案例。
最後,再用一個實際一點的例子說明,假設今天有個登入的表單元件,那麼最簡單預期會有的案例就會是:
describe('登入元件', () => {
// Happy Path
it('輸入正確帳號密碼,應登入到OO頁面', () => {
// ...
})
// Sad Path
it('只輸入帳號,應該顯示請輸入密碼', () => {
// ...
})
it('只輸入密碼,應該顯示請輸入帳號', () => {
// ...
})
it('輸入錯誤帳號密碼,應該顯示登入資訊錯誤', () => {
// ...
})
})
以上就是測試情境與測試案例最基本需要瞭解的部分,明天我們將關注於測試案例中內部應該要如何來撰寫。